package com.s7.compat.exception;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;

public class UncaughtException implements UncaughtExceptionHandler {

    public static final String TAG = "UncaughtException";

    private UncaughtExceptionHandler mDefaultHandler;

    private static volatile UncaughtException instance;

    private Context mContext;

    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/ExceptionCatch/log/";

    private static final String FILE_NAME = "catch";

    private static final String FLIE_NAME_SUFFIX = ".log";

    public UncaughtException() {

    }

    public static UncaughtException getInstance() {
        if (instance == null)
            synchronized (UncaughtException.class) {
                if (instance == null) {
                    instance = new UncaughtException();
                }
            }
        return instance;
    }

    public UncaughtException init(Context context) {
        mContext = context;

        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        return this;
    }


    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        if (!handleException(throwable) && mDefaultHandler != null) {

            mDefaultHandler.uncaughtException(thread, throwable);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }

            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }

    private boolean handleException(final Throwable ex) {
        if (ex == null || mContext == null) {
            return false;
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                try {
                    savcExceptionToSDCard(ex);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出。", Toast.LENGTH_SHORT).show();
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    Log.e(TAG, "error : ", e);
                }
                //退出程序
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
                Looper.loop();
            }
        }).start();
        return true;
    }

    private void savcExceptionToSDCard(final Throwable ex) throws IOException {

        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Log.w("TAG", "sdcard unmounted,skip save exception");
            return;
        }

        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        long current = System.currentTimeMillis();
        final String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
        File file = new File(PATH + FILE_NAME + FLIE_NAME_SUFFIX);
        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            pw.println(time);
            savePhoneInfo(pw, ex);
        } catch (Exception e) {
        }

//        if (mListener != null) {
//            mListener.onExceptionFile(file);
//        }
    }

    private void savePhoneInfo(PrintWriter pw, Throwable ex) throws PackageManager.NameNotFoundException {
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
        pw.print("App version: ");
        pw.print(pi.versionName);
        pw.print('_');
        pw.println(pi.versionCode);

        pw.print("OS Version: ");
        pw.print(Build.VERSION.RELEASE);
        pw.print(" _ sdk: ");
        pw.println(Build.VERSION.SDK_INT);

        pw.print("Vendor: ");
        pw.println(Build.MANUFACTURER);

        pw.print("Model: ");
        pw.println(Build.MODEL);

        pw.print("CPU ABI : ");
        pw.println(Build.CPU_ABI);
        pw.println();
        ex.printStackTrace(pw);
        pw.close();
    }

}
